/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.community.controller.evaluation.proof;

import cn.ac.nercis.pes.common.constant.evaluation.EvaluationModule;
import cn.ac.nercis.pes.common.constant.project.FinishState;
import cn.ac.nercis.pes.common.constant.project.SystemState;
import cn.ac.nercis.pes.community.component.controls.TreeListCell;
import cn.ac.nercis.pes.community.component.dialog.MessageDialog;
import cn.ac.nercis.pes.community.component.dialog.MessageType;
import cn.ac.nercis.pes.community.controller.base.InitEvalDataLoad;
import cn.ac.nercis.pes.community.model.vo.MenuVO;
import cn.ac.nercis.pes.community.support.AbstractFxmlView;
import cn.ac.nercis.pes.community.support.controls.JFXPopup;
import cn.ac.nercis.pes.community.utils.AppStore;
import cn.ac.nercis.pes.community.utils.ControlUtils;
import cn.ac.nercis.pes.community.utils.SpringUtils;
import cn.ac.nercis.pes.community.views.evaluation.proof.*;
import cn.ac.nercis.pes.model.dto.project.SystemProcessDTO;
import cn.ac.nercis.pes.service.project.SystemProcessService;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.net.URL;
import java.util.List;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;

/**
 * 密评证明记录管理控制器
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
public class ProofController implements Initializable {

    @FXML
    private StackPane page;
    @FXML
    private BorderPane bodyPane;

    @FXML
    private VBox expandPopupBox;

    @FXML
    private TreeView<MenuVO> menuTreeView;

    private final SystemProcessService processService;

    private TreeItem<MenuVO> rootMenu;

    private TreeItem<MenuVO> menuItem;
    ;
    private String currentSystemId;
    private JFXPopup expandPopup;

    private final BooleanProperty enablePaste = new SimpleBooleanProperty(false);

    public ProofController() {
        this.processService = SpringUtils.getBean(SystemProcessService.class);
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        rootMenu = new TreeItem<>(new MenuVO(0,"","密评证明记录菜单数据",""));
        this.initMenuControl();
    }

    public void initializeData(String systemId){
        this.currentSystemId = systemId;
        this.initMenuData();
        this.refreshEvalProcess();
    }

    public StackPane getPage(){
        return this.page;
    }

    public void refreshEvalProcess(){
        initMenuItemEvalState(processService.findSystemProcess(this.currentSystemId, SystemState.PROOF));
    }

    public void setEvalProcess(EvaluationModule menu, FinishState state){
        var process = SystemProcessDTO.builder()
                .systemId(this.currentSystemId)
                .state(SystemState.PROOF)
                .name(menu.getName())
                .finishState(state)
                .build();
        CompletableFuture.supplyAsync(() -> processService.setSystemProcess(process))
                .thenAccept(res -> Platform.runLater(() -> {
                    if (!res.isSuccess()) {
                        MessageDialog.builder()
                                .withType(MessageType.WARN)
                                .withMessage("记录密评证明记录测评进度失败")
                                .withContainer(page)
                                .build().show();
                    }else{
                        this.refreshEvalProcess();
                    }
                }))
                .exceptionally((ex) -> {
                    log.error("保存密评证明记录测评进度出错!", ex);
                    return null;
                });
    }

    private void initMenuControl() {
        menuTreeView.setCellFactory(tree -> new TreeListCell(10, true));
        menuTreeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (Objects.nonNull(newValue) && Objects.nonNull(newValue.getValue())) {
                loadPageContent(newValue);
                menuItem = newValue;
            }
        });
        menuTreeView.setRoot(rootMenu);
        menuTreeView.setShowRoot(false);
    }

    private void initMenuData() {
        rootMenu.getChildren().clear();
        EvaluationModule.findProofEvalModules()
                .forEach(em -> rootMenu.getChildren().add(new TreeItem<>(new MenuVO(1, "", em.getName(), "none-process-icon"))));
        menuTreeView.getSelectionModel().select(0);
    }

    private void initMenuItemEvalState(List<SystemProcessDTO> systemProcess) {
        rootMenu.getChildren().forEach(item -> {
            var menuItem = item.getValue();
            var state = systemProcess.stream()
                    .filter(sp-> StringUtils.equals(menuItem.getTitle(),sp.getName()))
                    .map(SystemProcessDTO::getFinishState)
                    .findFirst()
                    .orElse(FinishState.NONE);
            menuItem.setIcon(ControlUtils.finishStateToIcon(state));
            menuItem.setState(state);
        });
        menuTreeView.refresh();
    }

    private void loadPageContent(TreeItem<MenuVO> menuItem){
        var menuVO = menuItem.getValue();
        if (StringUtils.equals(menuVO.getTitle(),EvaluationModule.PROOF_DELEGATE.getName())) {
            this.loadPageContent(Objects.requireNonNull(AppStore.getEvaluationView(this.currentSystemId, DelegateView.class)));
        }  else if (StringUtils.equals(menuVO.getTitle(),EvaluationModule.PROOF_ACTIVITY.getName())) {
            this.loadPageContent(Objects.requireNonNull(AppStore.getEvaluationView(this.currentSystemId, ActivityView.class)));
        } else if (StringUtils.equals(menuVO.getTitle(),EvaluationModule.PROOF_QUALITY.getName())) {
            this.loadPageContent(Objects.requireNonNull(AppStore.getEvaluationView(this.currentSystemId, QualityView.class)));
        } else if (StringUtils.equals(menuVO.getTitle(),EvaluationModule.PROOF_PERSON.getName())) {
            this.loadPageContent(Objects.requireNonNull(AppStore.getEvaluationView(this.currentSystemId, PersonQualificationView.class)));
        } else if (StringUtils.equals(menuVO.getTitle(),EvaluationModule.PROOF_GRADING.getName())) {
            this.loadPageContent(Objects.requireNonNull(AppStore.getEvaluationView(this.currentSystemId, GradingView.class)));
        }
    }

    private void loadPageContent(@NonNull AbstractFxmlView view){
        bodyPane.setCenter(view.load());
        if(view.getController() instanceof InitEvalDataLoad controller){
            controller.initializeData(this.currentSystemId);
        }
    }
}